﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bzure.Security.Principal;
using Bzure.Common.Data;
using Bzure.Common.Transactions;
using Bzure.Security;
using Bzure.Security.Principal;
using Bzure.Security.Permissions;
using Bzure.Apps.Security;
using Bzure.Common.Core;

namespace System
{
    public static class UserExtensions
    {
        public static string MyDisplayName(this Me Me)
        {
            if (!Actor.Public.IsAuthenticated)
                return string.Empty;
            string name = string.Empty;
            if (Me.Principal.Identity is Bzure.Security.Principal.BzureUserModel)
            {
                Bzure.Security.Principal.BzureUserModel bum = Me.Principal.Identity as Bzure.Security.Principal.BzureUserModel;
                name = bum.Entity.NickName.IsNullOrEmpty() ? bum.Entity.UserName : bum.Entity.NickName;
            }
            else
            {
                name = Me.Principal.Identity.Name;
            }
            return name;
        }
        #region Authorize User
        public static void AuthorizeUser(this Public Public, BzureUser user, string[] RoleIDs, Action<bool> action)
        {
            string[] oldRoles = Actor.Public.AsRoleManager().GetTeamRoleIDsByUserID(user.UserID.ToString());
            BizTransaction transaction = BizTransaction.BeginTransaction();
            //step 1 修改用户状态
            RegisterFactor_UserState(transaction, user);
            //step 2 删除用户原有的全部角色
            RegisterFactor_DeleteRoles(transaction, user, oldRoles);
            //step 3 添加用户新的角色
            RegisterFactor_AddRoles(transaction, user, RoleIDs);
            bool ok = transaction.TryCommit();
            if (ok)
            {
                Actor.Public.UpdateLastPermissionChangeTime();
            }
            action(ok);
        }
        static void RegisterFactor_UserState(BizTransaction transaction, BzureUser user)
        {
            IEntityRequestProcess userStateProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> userStateFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(userStateProcessor);
            userStateFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            userStateFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {
                EntityPostRequest OrderRequest = BuilderUserStateRequest(user);
                action(userStateProcessor, OrderRequest);
            };

            transaction.RegisterFactor(userStateFactor);
        }
        static EntityPostRequest BuilderUserStateRequest(BzureUser user)
        {
            if (user.IsPersisted())
            {
                EntityPostRequest userStateRequest = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Update)
                {
                    Entity = user
                };
                userStateRequest.AppendFieldMap(user.State, () => user.State);
                userStateRequest.AppendConditionMap(user.UserID, () => user.UserID);
                return userStateRequest;
            }
            else
            {
                throw new Exception(string.Format("用户{0}还没有保存", user.UserName));
            }

        }
        static void RegisterFactor_DeleteRoles(BizTransaction transaction, BzureUser user, string[] oldRoles)
        {
            IEntityRequestProcess deleteRolesProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> deleteRolesFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(deleteRolesProcessor);
            deleteRolesFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            deleteRolesFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {
                foreach (string roleid in oldRoles)
                {
                    EntityPostRequest deleteRoleRequest = BuilddeleteRoleRequest(user.UserID.ToString(), roleid);
                    action(deleteRolesProcessor, deleteRoleRequest);
                }
            };

            transaction.RegisterFactor(deleteRolesFactor);
        }
        static EntityPostRequest BuilddeleteRoleRequest(string userid, string roleid)
        {
            UserRoleMap role = new UserRoleMap()
            {
                RoleID = roleid,
                UserID = userid
            };
            EntityPostRequest request = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Delete)
            {
                Entity = role
            };
            request.AppendConditionMap(role.UserID, () => role.UserID);
            request.AppendConditionMap(role.RoleID, () => role.RoleID);
            return request;
        }
        static void RegisterFactor_AddRoles(BizTransaction transaction, BzureUser user, string[] Roles)
        {
            IEntityRequestProcess addRolesProcessor = Actor.Public.BuildEntityProcessor("SecurityApp");
            TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>> addRolesFactor = new TransactionFactor<IEntityRequestProcess, Action<IEntityRequestProcess, EntityPostRequest>>(addRolesProcessor);
            addRolesFactor.ActionBody = (IEntityRequestProcess contract, EntityPostRequest request) =>
            {
                contract.UpdateEntity(request);
            };

            addRolesFactor.Action = (Action<IEntityRequestProcess, EntityPostRequest> action) =>
            {
                foreach (string roleid in Roles)
                {
                    EntityPostRequest addRoleRequest = BuildaddRoleRequest(user.UserID.ToString(), roleid);
                    action(addRolesProcessor, addRoleRequest);
                }
            };

            transaction.RegisterFactor(addRolesFactor);
        }
        static EntityPostRequest BuildaddRoleRequest(string userid, string roleid)
        {
            UserRoleMap role = new UserRoleMap()
            {
                RoleID = roleid,
                UserID = userid
            };
            EntityPostRequest request = new EntityPostRequest(EntityPostRequest.EntityPostMethod.Create)
            {
                Entity = role
            };
            request.AppendFieldMap(role.UserID, () => role.UserID);
            request.AppendFieldMap(role.RoleID, () => role.RoleID);
            return request;
        }
        #endregion
        #region BindUser
        public static void BindUser(this Public Public, string UserID, string BindID, string BindProvider)
        {            
            UserBind factor = new UserBind()
            {
                BindID = BindID,
                BindProvider = BindProvider
            };
            EntityQueryRequest<UserBind> query = new EntityQueryRequest<UserBind>();
            query.AppendConditionMap(factor.BindID, () => factor.BindID);
            query.AppendConditionMap(factor.BindProvider, () => factor.BindProvider);
            UserBind bind = Actor.Public.BuildEntityProcessor("SecurityApp").QueryEntity(query).FirstOrDefault();
            if (bind.IsNull())
            {
                bind = new UserBind()
                {
                    ID = Guid.NewGuid().ToString("N"),
                    BindID = BindID,
                    BindProvider = BindProvider
                };
            }
            bind.UserID = UserID;
            bind.UpdateEntity("SecurityApp");
        }
        #endregion
    }
}
